// 版权归Go作者所有。保留所有权利。
// 此源代码的使用受BSD样式
// 许可证的约束，该许可证可以在许可证文件中找到。

// 该软件包定义了Go对象文件格式，并提供了“低级”函数
// 用于读取和写入对象文件。

// 目标文件被编译器、汇编程序、链接器和工具理解。它们拥有对目标文件进行操作的“高级”代码，处理特定于应用程序的
// 逻辑，并使用此软件包进行实际的读写。具体来说，下面的代码是：
// 
// -cmd/internal/obj/objfile。go（由cmd/asm和cmd/compile使用）
// /-cmd/internal/objfile/goobj。go（使用cmd/nm，cmd/objdump）
// /-cmd/link/internal/loader package（由cmd/link使用）
// 
// 如果对象文件格式更改，它们可能（也可能不）需要更改。

package goobj

import (
	"cmd/internal/bio"
	"crypto/sha1"
	"encoding/binary"
	"errors"
	"fmt"
	"internal/unsafeheader"
	"unsafe"
)

// 新的对象文件格式。
// 
// 头结构{
// 魔法[…]字节
// 指纹[8]字节
// 标志uint32 
// 偏移量[…]uint32
// }
// 
// Strings[…]结构{
// 数据[…]字节
// /}
// 
// Autolib[…]结构{
// Pkg字符串
// Fingerprint[8]字节
// }
// 
// PkgIndex[…]字符串
// 
// 文件[…]字符串
// 
// SymbolDefs[…]结构{
// 名称字符串
// ABI uint16 
// 键入uint8 
// 标志uint8 
// 标志uint8 
// 大小uint32 
// /}
// 哈希64defs[…]结构{
// ……
// }
// HashedDefs[…]结构{
// 与SymbolDefs 
// /}
// /非KGDEFS[…]结构{
// …
// }
// non-kgrefs[…]结构{
// …
// }
// 
// RefFlags[…]结构{
// Sym symRef 
// Flag uint8 
// Flag2 uint8 
// }
// 
// Hash64[…][8] 字节
// 哈希[…][N] 字节
// 
// RelocIndex[…]uint32
// 生长素指数[…]uint32
// 数据索引[…]uint32
// 
// Relocs[…]struct{
// Off int32 
// Size uint8 
// Type uint16 
// Add int64 
// Sym symRef 
// }
// 
// Aux[…]结构{
// 类型uint8 
// Sym symRef 
// }
// 
// 数据[…]字节
// 
// /仅由工具使用的块（objdump，nm）
// 
// /参考名称[…]struct{
// Sym symRef 
// Name string 
// /TODO:也包括ABI version？
// }
// 
// 字符串编码为uint32长度，后跟uint32偏移量
// ，指向对应的字符串字节。
// 
// symRef是结构{PkgIdx，SymIdx uint32}。
// 
// 切片类型（例如，[]symRef）编码为长度前缀（uint32）
// 后跟该数量的元素。
// 
// 以下类型对应于
// 对象文件中的编码数据结构。

// 符号索引。
// 
// 每个符号都引用了一对索引，{PkgIdx，SymIdx}，
// 作为上面的symRef结构。
// 
// PkgIdx是预声明的索引（见下面的PkgIdxNone）或
// 导入包的索引。对于后一种情况，PkgIdx是PkgIndex数组中包的
// 索引。0是无效的索引。
// 
// SymIdx是给定包中符号的索引。
// -如果PkgIdx是PkgIdxSelf，则SymIdx是
// SymbolDefs数组中符号的索引。
// -如果PkgIdx是PkgIdxHashed64，则SymIdx是
// /Hashed64Defs数组中符号的索引。
// -如果PkgIdx是PkgIdxHashed，则SymIdx是
// HashedDefs数组中符号的索引。
// -如果PkgIdx是PkgIdxNone，则SymIdx是
// NonPkgDefs数组中符号的索引（可能会自然溢出到nonpkrefs数组）。
// -否则，SymIdx是其他包的
// SymbolDefs数组中符号的索引。
// 
// {0,0}表示零符号。否则PkgIdx不应为0。
// 
// 哈希包含内容可寻址符号的内容哈希，
// 哪个PkgIdx是PkgIdxHashed，顺序与HashedDefs数组相同。
// 对于PkgIdxHashed64符号，Hash64类似。
// 
// RelocIndex、AuxIndex和DataIndex包含指向
// Relocs/Aux/Data块的索引/偏移量，每个符号一个元素，首先是所有
// 定义的符号，然后是所有定义的散列和非包符号，
// 按照SymbolDefs/Hashed64Defs/HashedDefs/NonPkgDefs 
// 最后一个元素是重新定位的总数（辅助符号、数据
// 块等）。
// 
// 它们可以通过索引访问。对于第i个符号，它的重定位
// 是Relocs数组中的RelocIndex[i]-th（包含）到RelocIndex[i+1]-th（排除）
// 元素。Aux/数据也是如此。（索引为
// 0-based。）

// 辅助符号。
// 
// 每个符号可以（也可以不）与许多辅助
// 符号相关联。它们在Aux块中进行了描述。请参见下面的辅助结构。
// 当前一个符号的Gotype、FuncInfo和相关的矮符号
// 是辅助符号。

const stringRefSize = 8 // 两个单元

type FingerprintType [8]byte

func (fp FingerprintType) IsZero() bool { return fp == FingerprintType{} }

// 包索引。
const (
	PkgIdxNone     = (1<<31 - 1) - iota // 非包符号
	PkgIdxHashed64                      // 短哈希（内容可寻址）符号
	PkgIdxHashed                        // 哈希（内容可寻址）符号
	PkgIdxBuiltin                       // 预定义的运行时符号（例如：runtime.newobject）
	PkgIdxSelf                          // 当前包中定义的符号
	PkgIdxInvalid  = 0
	// 其他引用包的索引从1开始。
)

// 块
const (
	BlkAutolib = iota
	BlkPkgIdx
	BlkFile
	BlkSymdef
	BlkHashed64def
	BlkHasheddef
	BlkNonpkgdef
	BlkNonpkgref
	BlkRefFlags
	BlkHash64
	BlkHash
	BlkRelocIdx
	BlkAuxIdx
	BlkDataIdx
	BlkReloc
	BlkAux
	BlkData
	BlkRefName
	BlkEnd
	NBlk
)

// 文件头。
// TODO:可能不需要导出这个。
type Header struct {
	Magic       string
	Fingerprint FingerprintType
	Flags       uint32
	Offsets     [NBlk]uint32
}

const Magic = "\x00go118ld"

func (h *Header) Write(w *Writer) {
	w.RawString(h.Magic)
	w.Bytes(h.Fingerprint[:])
	w.Uint32(h.Flags)
	for _, x := range h.Offsets {
		w.Uint32(x)
	}
}

func (h *Header) Read(r *Reader) error {
	b := r.BytesAt(0, len(Magic))
	h.Magic = string(b)
	if h.Magic != Magic {
		return errors.New("wrong magic, not a Go object file")
	}
	off := uint32(len(h.Magic))
	copy(h.Fingerprint[:], r.BytesAt(off, len(h.Fingerprint)))
	off += 8
	h.Flags = r.uint32At(off)
	off += 4
	for i := range h.Offsets {
		h.Offsets[i] = r.uint32At(off)
		off += 4
	}
	return nil
}

func (h *Header) Size() int {
	return len(h.Magic) + 4 + 4*len(h.Offsets)
}

// 自动库
type ImportedPkg struct {
	Pkg         string
	Fingerprint FingerprintType
}

const importedPkgSize = stringRefSize + 8

func (p *ImportedPkg) Write(w *Writer) {
	w.StringRef(p.Pkg)
	w.Bytes(p.Fingerprint[:])
}

// 符号定义。
// 
// 序列化格式：
// Sym struct{
// 名称字符串
// ABI uint16 
// 类型uint8 
// 标志uint8 
// 标志uint8 
// 大小uint32 
type Sym [SymSize]byte

const SymSize = stringRefSize + 2 + 1 + 1 + 1 + 4 + 4

const SymABIstatic = ^uint16(0)

const (
	ObjFlagNeedNameExpansion             // 链接器需要扩展“.”要在符号名
	ObjFlagFromAssembly                  // 中打包路径，对象来自asm src，而不是去
)

// Sym。旗帜
const (
	SymFlagDupok = 1 << iota
	SymFlagLocal
	SymFlagTypelink
	SymFlagLeaf
	SymFlagNoSplit
	SymFlagReflectMethod
	SymFlagGoType
)

// Sym。Flag2 
const (
	SymFlagUsedInIface = 1 << iota
	SymFlagItab
	SymFlagDict
)

// 返回符号名称的长度。
func (s *Sym) NameLen(r *Reader) int {
	return int(binary.LittleEndian.Uint32(s[:]))
}

func (s *Sym) Name(r *Reader) string {
	len := binary.LittleEndian.Uint32(s[:])
	off := binary.LittleEndian.Uint32(s[4:])
	return r.StringAt(off, len)
}

func (s *Sym) ABI() uint16   { return binary.LittleEndian.Uint16(s[8:]) }
func (s *Sym) Type() uint8   { return s[10] }
func (s *Sym) Flag() uint8   { return s[11] }
func (s *Sym) Flag2() uint8  { return s[12] }
func (s *Sym) Siz() uint32   { return binary.LittleEndian.Uint32(s[13:]) }
func (s *Sym) Align() uint32 { return binary.LittleEndian.Uint32(s[17:]) }

func (s *Sym) Dupok() bool         { return s.Flag()&SymFlagDupok != 0 }
func (s *Sym) Local() bool         { return s.Flag()&SymFlagLocal != 0 }
func (s *Sym) Typelink() bool      { return s.Flag()&SymFlagTypelink != 0 }
func (s *Sym) Leaf() bool          { return s.Flag()&SymFlagLeaf != 0 }
func (s *Sym) NoSplit() bool       { return s.Flag()&SymFlagNoSplit != 0 }
func (s *Sym) ReflectMethod() bool { return s.Flag()&SymFlagReflectMethod != 0 }
func (s *Sym) IsGoType() bool      { return s.Flag()&SymFlagGoType != 0 }
func (s *Sym) UsedInIface() bool   { return s.Flag2()&SymFlagUsedInIface != 0 }
func (s *Sym) IsItab() bool        { return s.Flag2()&SymFlagItab != 0 }
func (s *Sym) IsDict() bool        { return s.Flag2()&SymFlagDict != 0 }

func (s *Sym) SetName(x string, w *Writer) {
	binary.LittleEndian.PutUint32(s[:], uint32(len(x)))
	binary.LittleEndian.PutUint32(s[4:], w.stringOff(x))
}

func (s *Sym) SetABI(x uint16)   { binary.LittleEndian.PutUint16(s[8:], x) }
func (s *Sym) SetType(x uint8)   { s[10] = x }
func (s *Sym) SetFlag(x uint8)   { s[11] = x }
func (s *Sym) SetFlag2(x uint8)  { s[12] = x }
func (s *Sym) SetSiz(x uint32)   { binary.LittleEndian.PutUint32(s[13:], x) }
func (s *Sym) SetAlign(x uint32) { binary.LittleEndian.PutUint32(s[17:], x) }

func (s *Sym) Write(w *Writer) { w.Bytes(s[:]) }

// 用于测试
func (s *Sym) fromBytes(b []byte) { copy(s[:], b) }

// 符号参考。
type SymRef struct {
	PkgIdx uint32
	SymIdx uint32
}

func (s SymRef) IsZero() bool { return s == SymRef{} }

// 哈希64 
type Hash64Type [Hash64Size]byte

const Hash64Size = 8

// 哈希
type HashType [HashSize]byte

const HashSize = sha1.Size

// 重新定位。
// 
// 序列化格式：
// Reloc struct{
// Off int32 
// SIZUINT8 
// Type uint16 
// Add int64 
// Sym SYMEREF 
// /}
type Reloc [RelocSize]byte

const RelocSize = 4 + 1 + 2 + 8 + 8

func (r *Reloc) Off() int32   { return int32(binary.LittleEndian.Uint32(r[:])) }
func (r *Reloc) Siz() uint8   { return r[4] }
func (r *Reloc) Type() uint16 { return binary.LittleEndian.Uint16(r[5:]) }
func (r *Reloc) Add() int64   { return int64(binary.LittleEndian.Uint64(r[7:])) }
func (r *Reloc) Sym() SymRef {
	return SymRef{binary.LittleEndian.Uint32(r[15:]), binary.LittleEndian.Uint32(r[19:])}
}

func (r *Reloc) SetOff(x int32)   { binary.LittleEndian.PutUint32(r[:], uint32(x)) }
func (r *Reloc) SetSiz(x uint8)   { r[4] = x }
func (r *Reloc) SetType(x uint16) { binary.LittleEndian.PutUint16(r[5:], x) }
func (r *Reloc) SetAdd(x int64)   { binary.LittleEndian.PutUint64(r[7:], uint64(x)) }
func (r *Reloc) SetSym(x SymRef) {
	binary.LittleEndian.PutUint32(r[15:], x.PkgIdx)
	binary.LittleEndian.PutUint32(r[19:], x.SymIdx)
}

func (r *Reloc) Set(off int32, size uint8, typ uint16, add int64, sym SymRef) {
	r.SetOff(off)
	r.SetSiz(size)
	r.SetType(typ)
	r.SetAdd(add)
	r.SetSym(sym)
}

func (r *Reloc) Write(w *Writer) { w.Bytes(r[:]) }

func (r *Reloc) fromBytes(b []byte) { copy(r[:], b) }

// 
// 序列化格式：
// 辅助结构{
// 类型uint8 
// Sym SYMREFG 
// /}
type Aux [AuxSize]byte

const AuxSize = 1 + 8

// 辅助类型
const (
	AuxGotype = iota
	AuxFuncInfo
	AuxFuncdata
	AuxDwarfInfo
	AuxDwarfLoc
	AuxDwarfRanges
	AuxDwarfLines
	AuxPcsp
	AuxPcfile
	AuxPcline
	AuxPcinline
	AuxPcdata
)

func (a *Aux) Type() uint8 { return a[0] }
func (a *Aux) Sym() SymRef {
	return SymRef{binary.LittleEndian.Uint32(a[1:]), binary.LittleEndian.Uint32(a[5:])}
}

func (a *Aux) SetType(x uint8) { a[0] = x }
func (a *Aux) SetSym(x SymRef) {
	binary.LittleEndian.PutUint32(a[1:], x.PkgIdx)
	binary.LittleEndian.PutUint32(a[5:], x.SymIdx)
}

func (a *Aux) Write(w *Writer) { w.Bytes(a[:]) }

// 用于测试
func (a *Aux) fromBytes(b []byte) { copy(a[:], b) }

// 引用的符号标志。
// 
// 序列化格式：
// RefFlags结构{
// Sym symRef 
// Flag uint8 
// Flag 2 uint8 
// /}
type RefFlags [RefFlagsSize]byte

const RefFlagsSize = 8 + 1 + 1

func (r *RefFlags) Sym() SymRef {
	return SymRef{binary.LittleEndian.Uint32(r[:]), binary.LittleEndian.Uint32(r[4:])}
}
func (r *RefFlags) Flag() uint8  { return r[8] }
func (r *RefFlags) Flag2() uint8 { return r[9] }

func (r *RefFlags) SetSym(x SymRef) {
	binary.LittleEndian.PutUint32(r[:], x.PkgIdx)
	binary.LittleEndian.PutUint32(r[4:], x.SymIdx)
}
func (r *RefFlags) SetFlag(x uint8)  { r[8] = x }
func (r *RefFlags) SetFlag2(x uint8) { r[9] = x }

func (r *RefFlags) Write(w *Writer) { w.Bytes(r[:]) }

// 用于在从对象文件relocs部分或aux sym部分读取
// 项时构造人工大数组类型（需要
// 才能在32位和64位上工作）。见第41621期。
const huge = (1<<31 - 1) / RelocSize

// 引用的符号名称。
// 
// 序列化格式：
// RefName结构{
// Sym symRef 
// 名称字符串
// }
type RefName [RefNameSize]byte

const RefNameSize = 8 + stringRefSize

func (n *RefName) Sym() SymRef {
	return SymRef{binary.LittleEndian.Uint32(n[:]), binary.LittleEndian.Uint32(n[4:])}
}
func (n *RefName) Name(r *Reader) string {
	len := binary.LittleEndian.Uint32(n[8:])
	off := binary.LittleEndian.Uint32(n[12:])
	return r.StringAt(off, len)
}

func (n *RefName) SetSym(x SymRef) {
	binary.LittleEndian.PutUint32(n[:], x.PkgIdx)
	binary.LittleEndian.PutUint32(n[4:], x.SymIdx)
}
func (n *RefName) SetName(x string, w *Writer) {
	binary.LittleEndian.PutUint32(n[8:], uint32(len(x)))
	binary.LittleEndian.PutUint32(n[12:], w.stringOff(x))
}

func (n *RefName) Write(w *Writer) { w.Bytes(n[:]) }

type Writer struct {
	wr        *bio.Writer
	stringMap map[string]uint32
	off       uint32 // 运行偏移量
}

func NewWriter(wr *bio.Writer) *Writer {
	return &Writer{wr: wr, stringMap: make(map[string]uint32)}
}

func (w *Writer) AddString(s string) {
	if _, ok := w.stringMap[s]; ok {
		return
	}
	w.stringMap[s] = w.off
	w.RawString(s)
}

func (w *Writer) stringOff(s string) uint32 {
	off, ok := w.stringMap[s]
	if !ok {
		panic(fmt.Sprintf("writeStringRef: string not added: %q", s))
	}
	return off
}

func (w *Writer) StringRef(s string) {
	w.Uint32(uint32(len(s)))
	w.Uint32(w.stringOff(s))
}

func (w *Writer) RawString(s string) {
	w.wr.WriteString(s)
	w.off += uint32(len(s))
}

func (w *Writer) Bytes(s []byte) {
	w.wr.Write(s)
	w.off += uint32(len(s))
}

func (w *Writer) Uint64(x uint64) {
	var b [8]byte
	binary.LittleEndian.PutUint64(b[:], x)
	w.wr.Write(b[:])
	w.off += 8
}

func (w *Writer) Uint32(x uint32) {
	var b [4]byte
	binary.LittleEndian.PutUint32(b[:], x)
	w.wr.Write(b[:])
	w.off += 4
}

func (w *Writer) Uint16(x uint16) {
	var b [2]byte
	binary.LittleEndian.PutUint16(b[:], x)
	w.wr.Write(b[:])
	w.off += 2
}

func (w *Writer) Uint8(x uint8) {
	w.wr.WriteByte(x)
	w.off++
}

func (w *Writer) Offset() uint32 {
	return w.off
}

type Reader struct {
	b        []byte // mmapped，如果不是nil 
	readonly bool   // b是否支持只读内存

	start uint32
	h     Header // 保持块偏移量
}

func NewReaderFromBytes(b []byte, readonly bool) *Reader {
	r := &Reader{b: b, readonly: readonly, start: 0}
	err := r.h.Read(r)
	if err != nil {
		return nil
	}
	return r
}

func (r *Reader) BytesAt(off uint32, len int) []byte {
	if len == 0 {
		return nil
	}
	end := int(off) + len
	return r.b[int(off):end:end]
}

func (r *Reader) uint64At(off uint32) uint64 {
	b := r.BytesAt(off, 8)
	return binary.LittleEndian.Uint64(b)
}

func (r *Reader) int64At(off uint32) int64 {
	return int64(r.uint64At(off))
}

func (r *Reader) uint32At(off uint32) uint32 {
	b := r.BytesAt(off, 4)
	return binary.LittleEndian.Uint32(b)
}

func (r *Reader) int32At(off uint32) int32 {
	return int32(r.uint32At(off))
}

func (r *Reader) uint16At(off uint32) uint16 {
	b := r.BytesAt(off, 2)
	return binary.LittleEndian.Uint16(b)
}

func (r *Reader) uint8At(off uint32) uint8 {
	b := r.BytesAt(off, 1)
	return b[0]
}

func (r *Reader) StringAt(off uint32, len uint32) string {
	b := r.b[off : off+len]
	if r.readonly {
		return toString(b) // 支持RO内存，确定使不安全字符串
	}
	return string(b)
}

func toString(b []byte) string {
	if len(b) == 0 {
		return ""
	}

	var s string
	hdr := (*unsafeheader.String)(unsafe.Pointer(&s))
	hdr.Data = unsafe.Pointer(&b[0])
	hdr.Len = len(b)

	return s
}

func (r *Reader) StringRef(off uint32) string {
	l := r.uint32At(off)
	return r.StringAt(r.uint32At(off+4), l)
}

func (r *Reader) Fingerprint() FingerprintType {
	return r.h.Fingerprint
}

func (r *Reader) Autolib() []ImportedPkg {
	n := (r.h.Offsets[BlkAutolib+1] - r.h.Offsets[BlkAutolib]) / importedPkgSize
	s := make([]ImportedPkg, n)
	off := r.h.Offsets[BlkAutolib]
	for i := range s {
		s[i].Pkg = r.StringRef(off)
		copy(s[i].Fingerprint[:], r.BytesAt(off+stringRefSize, len(s[i].Fingerprint)))
		off += importedPkgSize
	}
	return s
}

func (r *Reader) Pkglist() []string {
	n := (r.h.Offsets[BlkPkgIdx+1] - r.h.Offsets[BlkPkgIdx]) / stringRefSize
	s := make([]string, n)
	off := r.h.Offsets[BlkPkgIdx]
	for i := range s {
		s[i] = r.StringRef(off)
		off += stringRefSize
	}
	return s
}

func (r *Reader) NPkg() int {
	return int(r.h.Offsets[BlkPkgIdx+1]-r.h.Offsets[BlkPkgIdx]) / stringRefSize
}

func (r *Reader) Pkg(i int) string {
	off := r.h.Offsets[BlkPkgIdx] + uint32(i)*stringRefSize
	return r.StringRef(off)
}

func (r *Reader) NFile() int {
	return int(r.h.Offsets[BlkFile+1]-r.h.Offsets[BlkFile]) / stringRefSize
}

func (r *Reader) File(i int) string {
	off := r.h.Offsets[BlkFile] + uint32(i)*stringRefSize
	return r.StringRef(off)
}

func (r *Reader) NSym() int {
	return int(r.h.Offsets[BlkSymdef+1]-r.h.Offsets[BlkSymdef]) / SymSize
}

func (r *Reader) NHashed64def() int {
	return int(r.h.Offsets[BlkHashed64def+1]-r.h.Offsets[BlkHashed64def]) / SymSize
}

func (r *Reader) NHasheddef() int {
	return int(r.h.Offsets[BlkHasheddef+1]-r.h.Offsets[BlkHasheddef]) / SymSize
}

func (r *Reader) NNonpkgdef() int {
	return int(r.h.Offsets[BlkNonpkgdef+1]-r.h.Offsets[BlkNonpkgdef]) / SymSize
}

func (r *Reader) NNonpkgref() int {
	return int(r.h.Offsets[BlkNonpkgref+1]-r.h.Offsets[BlkNonpkgref]) / SymSize
}

// SymOff返回第i个符号的偏移量。
func (r *Reader) SymOff(i uint32) uint32 {
	return r.h.Offsets[BlkSymdef] + uint32(i*SymSize)
}

// Sym返回指向第i个符号的指针。
func (r *Reader) Sym(i uint32) *Sym {
	off := r.SymOff(i)
	return (*Sym)(unsafe.Pointer(&r.b[off]))
}

// nReflags返回被引用符号标志的数量。
func (r *Reader) NRefFlags() int {
	return int(r.h.Offsets[BlkRefFlags+1]-r.h.Offsets[BlkRefFlags]) / RefFlagsSize
}

// RefFlags返回指向第i个引用符号标志的指针。
// 注意：这里我不是一个本地符号索引，只是一个计数器。
func (r *Reader) RefFlags(i int) *RefFlags {
	off := r.h.Offsets[BlkRefFlags] + uint32(i*RefFlagsSize)
	return (*RefFlags)(unsafe.Pointer(&r.b[off]))
}

// Hash64返回第i个短哈希符号的哈希值。
// 注意：这里我是短散列符号的索引，不是所有符号
// （与其他访问器不同）。
func (r *Reader) Hash64(i uint32) uint64 {
	off := r.h.Offsets[BlkHash64] + uint32(i*Hash64Size)
	return r.uint64At(off)
}

// 散列返回指向第i个散列符号的散列的指针。
// 注意：这里我是散列符号的索引，不是所有符号
// （与其他访问器不同）。
func (r *Reader) Hash(i uint32) *HashType {
	off := r.h.Offsets[BlkHash] + uint32(i*HashSize)
	return (*HashType)(unsafe.Pointer(&r.b[off]))
}

// NReloc返回第i个符号的重新定位次数。
func (r *Reader) NReloc(i uint32) int {
	relocIdxOff := r.h.Offsets[BlkRelocIdx] + uint32(i*4)
	return int(r.uint32At(relocIdxOff+4) - r.uint32At(relocIdxOff))
}

// RelocOff返回第i个符号的第j次重新定位的偏移量。
func (r *Reader) RelocOff(i uint32, j int) uint32 {
	relocIdxOff := r.h.Offsets[BlkRelocIdx] + uint32(i*4)
	relocIdx := r.uint32At(relocIdxOff)
	return r.h.Offsets[BlkReloc] + (relocIdx+uint32(j))*uint32(RelocSize)
}

// Reloc返回指向第i个符号的第j个重定位的指针。
func (r *Reader) Reloc(i uint32, j int) *Reloc {
	off := r.RelocOff(i, j)
	return (*Reloc)(unsafe.Pointer(&r.b[off]))
}

// Relocs返回指向第i个符号重新定位的指针。
func (r *Reader) Relocs(i uint32) []Reloc {
	off := r.RelocOff(i, 0)
	n := r.NReloc(i)
	return (*[huge]Reloc)(unsafe.Pointer(&r.b[off]))[:n:n]
}

// NAux返回第i个符号的辅助符号数。
func (r *Reader) NAux(i uint32) int {
	auxIdxOff := r.h.Offsets[BlkAuxIdx] + i*4
	return int(r.uint32At(auxIdxOff+4) - r.uint32At(auxIdxOff))
}

// AuxOff返回第i个符号的第j个辅助符号的偏移量。
func (r *Reader) AuxOff(i uint32, j int) uint32 {
	auxIdxOff := r.h.Offsets[BlkAuxIdx] + i*4
	auxIdx := r.uint32At(auxIdxOff)
	return r.h.Offsets[BlkAux] + (auxIdx+uint32(j))*uint32(AuxSize)
}

// Aux返回指向第i个符号的第j个Aux符号的指针。
func (r *Reader) Aux(i uint32, j int) *Aux {
	off := r.AuxOff(i, j)
	return (*Aux)(unsafe.Pointer(&r.b[off]))
}

// Auxs返回第i个符号的辅助符号。
func (r *Reader) Auxs(i uint32) []Aux {
	off := r.AuxOff(i, 0)
	n := r.NAux(i)
	return (*[huge]Aux)(unsafe.Pointer(&r.b[off]))[:n:n]
}

// DataOff返回第i个符号数据的偏移量。
func (r *Reader) DataOff(i uint32) uint32 {
	dataIdxOff := r.h.Offsets[BlkDataIdx] + i*4
	return r.h.Offsets[BlkData] + r.uint32At(dataIdxOff)
}

// DataSize返回第i个符号数据的大小。
func (r *Reader) DataSize(i uint32) int {
	dataIdxOff := r.h.Offsets[BlkDataIdx] + i*4
	return int(r.uint32At(dataIdxOff+4) - r.uint32At(dataIdxOff))
}

// 数据返回第i个符号的数据。
func (r *Reader) Data(i uint32) []byte {
	dataIdxOff := r.h.Offsets[BlkDataIdx] + i*4
	base := r.h.Offsets[BlkData]
	off := r.uint32At(dataIdxOff)
	end := r.uint32At(dataIdxOff + 4)
	return r.BytesAt(base+off, int(end-off))
}

// NRefName返回引用的符号名称的数量。
func (r *Reader) NRefName() int {
	return int(r.h.Offsets[BlkRefName+1]-r.h.Offsets[BlkRefName]) / RefNameSize
}

// RefName返回指向第i个引用符号名的指针。
// 注意：这里我不是一个本地符号索引，只是一个计数器。
func (r *Reader) RefName(i int) *RefName {
	off := r.h.Offsets[BlkRefName] + uint32(i*RefNameSize)
	return (*RefName)(unsafe.Pointer(&r.b[off]))
}

// ReadOnly返回r.BytesAt是否返回只读字节。
func (r *Reader) ReadOnly() bool {
	return r.readonly
}

// Flags返回从对象文件头读取的标志位。
func (r *Reader) Flags() uint32 {
	return r.h.Flags
}

func (r *Reader) Shared() bool            { return r.Flags()&ObjFlagShared != 0 }
func (r *Reader) NeedNameExpansion() bool { return r.Flags()&ObjFlagNeedNameExpansion != 0 }
func (r *Reader) FromAssembly() bool      { return r.Flags()&ObjFlagFromAssembly != 0 }
